// 区间改，区间查
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 100007; // 最大数组长度
int n, m;                // n: 数组长度, m: 操作次数
ll a[maxn];              // 原始数组

struct SegmentTree {
  ll sum[maxn * 4], lazy[maxn * 4]; // sum: 区间和, lazy: 延迟标记

  // 上推操作：用子节点更新父节点的值
  void pushup(int u) { sum[u] = sum[2 * u] + sum[2 * u + 1]; }

  // 下推操作：将延迟标记传递给子节点
  // u: 当前节点编号
  // l: 当前节点表示的区间左端点
  // r: 当前节点表示的区间右端点
  void pushdown(int u, int l, int r) {
    int mid = (l + r) / 2;

    lazy[2 * u] += lazy[u];
    sum[2 * u] += lazy[u] * (mid - l + 1); // 更新左子区间和

    lazy[2 * u + 1] += lazy[u];
    sum[2 * u + 1] += lazy[u] * (r - mid); // 更新右子区间和

    lazy[u] = 0; // 清除当前节点的延迟标记
  }

  // 构建线段树
  // u: 当前节点编号
  // l: 当前节点表示的区间左端点
  // r: 当前节点表示的区间右端点
  // arr: 原始数组指针
  void build(int u, int l, int r, ll arr[]) {
    lazy[u] = 0;
    if (l == r) { // 叶子节点
      sum[u] = arr[l];
      return;
    }
    int mid = (l + r) / 2;
    build(2 * u, l, mid, arr);         // 递归构建左子树
    build(2 * u + 1, mid + 1, r, arr); // 递归构建右子树
    pushup(u);                         // 更新当前节点的值
  }

  // 区间更新操作
  // u: 当前节点编号
  // l: 当前节点表示的区间左端点
  // r: 当前节点表示的区间右端点
  // ql: 查询/更新区间左端点
  // qr: 查询/更新区间右端点
  // k: 要增加的数值
  void update(int u, int l, int r, int ql, int qr, ll k) {
    if (ql <= l && r <= qr) { // 当前区间完全包含在查询区间内
      lazy[u] += k;
      sum[u] += k * (r - l + 1); // 更新区间和
      return;
    }
    if (ql > r || qr < l) // 当前区间与查询区间无交集
      return;
    int mid = (l + r) / 2;
    pushdown(u, l, r);                        // 下推延迟标记
    update(2 * u, l, mid, ql, qr, k);         // 更新左子树
    update(2 * u + 1, mid + 1, r, ql, qr, k); // 更新右子树
    pushup(u);                                // 上推更新当前节点的值
  }

  // 区间查询操作
  // u: 当前节点编号
  // l: 当前节点表示的区间左端点
  // r: 当前节点表示的区间右端点
  // ql: 查询区间左端点
  // qr: 查询区间右端点
  // 返回值: 区间[ql, qr]的和
  ll query(int u, int l, int r, int ql, int qr) {
    if (ql <= l && r <= qr) { // 当前区间完全包含在查询区间内
      return sum[u];
    }
    if (ql > r || qr < l) // 当前区间与查询区间无交集
      return 0;
    int mid = (l + r) / 2;
    pushdown(u, l, r); // 下推延迟标记
    ll ret = 0;
    ret += query(2 * u, l, mid, ql, qr);         // 查询左子树
    ret += query(2 * u + 1, mid + 1, r, ql, qr); // 查询右子树
    return ret;
  }
};

int main() {
  cin >> n >> m;
  for (int i = 1; i <= n; i++)
    cin >> a[i];

  SegmentTree st;
  st.build(1, 1, n, a);

  for (int i = 1; i <= m; i++) {
    int op;
    cin >> op;
    if (op == 1) {
      ll x, y, k;
      cin >> x >> y >> k;
      // 更新区间[x, y]的每一个值增加k
      st.update(1, 1, n, x, y, k);
    } else {
      ll x, y;
      cin >> x >> y;
      // 查询区间[x, y]的和
      cout << st.query(1, 1, n, x, y) << endl;
    }
  }
}